package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.common.constant.CommonConstant;
import com.cskaoyan.wordmemorize.common.constant.ResultCodeEnum;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.converter.UserPrivilegeConverter;
import com.cskaoyan.wordmemorize.dao.entity.*;
import com.cskaoyan.wordmemorize.dao.mapper.*;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.admin.UserVocAISituationDTO;
import com.cskaoyan.wordmemorize.dto.app.*;
import com.cskaoyan.wordmemorize.request.AIReviewReadCommand;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.UserFavoriteCommand;
import com.cskaoyan.wordmemorize.request.UserVocExampleSentenceCommand;
import com.cskaoyan.wordmemorize.service.UserPrivilegeService;
import com.cskaoyan.wordmemorize.service.VocService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class UserPrivilegeServiceImpl implements UserPrivilegeService {

    @Autowired
    UserNotRememberMapper userNotRememberMapper;

    @Autowired
    UserVocRevMapper userVocRevMapper;

    @Autowired
    UserFavoriteMapper userFavoriteMapper;

    @Autowired
    VocMeaningMapper vocMeaningMapper;

    @Autowired
    VocBookMapper vocBookMapper;

    @Autowired
    VocChapBookMapper vocChapBookMapper;

    @Autowired
    UserPrivilegeConverter userPrivilegeConverter;

    @Autowired
    UserVocExampleSentenceMapper userVocExampleSentenceMapper;

    @Autowired
    UserVocAISituationMapper userVocAISituationMapper;

    @Autowired
    UserVocAISituationOptionMapper userVocAISituationOptionMapper;

    @Autowired
    UserPrivilegeHistoryMapper userPrivilegeHistoryMapper;

    @Autowired
    UserVocBoundStatisticsMapper userVocBoundStatisticsMapper;

    @Autowired
    AIReadGenerator aiReadGenerator;
    @Autowired
    UserVocBoundLogMapper userVocBoundLogMapper;
    @Autowired
    VocService vocService;

    /**
     * 获取用户单词本统计信息
     *
     * @param userId
     * @param bookId
     * @return
     */
    @Override
    public UserVocBookStatisticsDTO getSelectedBookStatistics(Long userId, Long bookId) {
        // 1. 获取词书信息及总单词数
        VocBookDO book = vocBookMapper.selectById(bookId);
        if (book == null) {
            throw new BusinessException(ResultCodeEnum.VOC_NOT_EXISTED);
        }
        int totalWords = book.getVocCount();

        // 2. 获取该词书下所有单词ID
        List<Long> bookVocIds = vocChapBookMapper.selectList(
                new LambdaQueryWrapper<VocChapBookDO>()
                        .eq(VocChapBookDO::getBookId, bookId)
                        .select(VocChapBookDO::getVocId)
        ).stream().map(VocChapBookDO::getVocId).collect(Collectors.toList());

        // 3. 初始化统计结果
        UserVocBookStatisticsDTO statistics = new UserVocBookStatisticsDTO();
        statistics.setTotal(totalWords);

        if (bookVocIds.isEmpty()) {
            statistics.setUnSelected(totalWords);
            return statistics;
        }

        // 4. 查询用户对这些单词的学习记录
        List<UserVocRevDO> userRecords = userVocRevMapper.selectList(
                new LambdaQueryWrapper<UserVocRevDO>()
                        .eq(UserVocRevDO::getUserId, userId)
                        .in(UserVocRevDO::getVocId, bookVocIds)
        );

        // 5. 统计各种状态的单词数量
        int familiarCount = 0;    // 熟悉: 复习间隔 >= 365
        int generalCount = 0;     // 一般: 1 < 复习间隔 < 365
        int unFamiliarCount = 0;  // 不熟悉: 复习间隔 = 1
        int notStartedCount = 0;  // 未开始: type = 0 (已选未学)
        int selectedCount = userRecords.size(); // 已选总数

        for (UserVocRevDO record : userRecords) {
            if ((record.getType() != null && record.getType() == 0)) {
                notStartedCount++;
            } else if (record.getReviewInterval() != null) {
                if (record.getReviewInterval() >= 365) {
                    familiarCount++;
                } else if (record.getReviewInterval() == 1) {
                    unFamiliarCount++;
                } else if (record.getReviewInterval() > 1) {
                    generalCount++;
                }
            }
        }

        // 6. 设置统计结果
        statistics.setFamiliar(familiarCount);
        statistics.setGeneral(generalCount);
        statistics.setUnFamiliar(unFamiliarCount);
        statistics.setNotStarted(notStartedCount);
        statistics.setTotal(totalWords);
        statistics.setUnSelected(totalWords - selectedCount);
        return statistics;

    }

    /**
     * 批量添加收藏单词
     *
     * @param
     * @param userId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addFavoriteBulk(List<UserFavoriteCommand> commands, Long userId) {
        if (CollectionUtils.isEmpty(commands)) {
            return;
        }

        // 1. 批量查询已存在的收藏
        List<String> vocIds = commands.stream()
                .map(UserFavoriteCommand::getVocId)
                .collect(Collectors.toList());

        Set<Long> existingIds = userFavoriteMapper.selectList(
                new LambdaQueryWrapper<UserFavoriteDO>()
                        .select(UserFavoriteDO::getVocId)
                        .eq(UserFavoriteDO::getUserId, userId)
                        .in(UserFavoriteDO::getVocId, vocIds)
        ).stream().map(UserFavoriteDO::getVocId).collect(Collectors.toSet());

        // 2. 批量查询复习状态
        Set<Long> reviewedIds = userVocRevMapper.selectList(
                new LambdaQueryWrapper<UserVocRevDO>()
                        .select(UserVocRevDO::getVocId)
                        .eq(UserVocRevDO::getUserId, userId)
                        .in(UserVocRevDO::getVocId, vocIds)
        ).stream().map(UserVocRevDO::getVocId).collect(Collectors.toSet());

        // 3. 逐个插入
        for (UserFavoriteCommand cmd : commands) {
            if (!existingIds.contains(cmd.getVocId())) {
                UserFavoriteDO favorite = userPrivilegeConverter.userFavoriteCommand2DO(cmd);
                favorite.setUserId(userId);
                favorite.setVocContent(String.valueOf(vocService.getVocById(Long.valueOf(cmd.getVocId())).getContent()));
                favorite.setSelected(reviewedIds.contains(cmd.getVocId()) ? 1 : 0);
                userFavoriteMapper.insert(favorite);
            }
        }
    }

    /**
     * 单个添加收藏单词
     *
     * @param userFavoriteCommand
     * @param userId
     */
    @Override
    public void addFavorite(UserFavoriteCommand userFavoriteCommand, Long userId) {

        // 检查是否已收藏
        UserFavoriteDO existing = userFavoriteMapper.selectOne(
                new LambdaQueryWrapper<UserFavoriteDO>()
                        .eq(UserFavoriteDO::getUserId, userId)
                        .eq(UserFavoriteDO::getVocId, userFavoriteCommand.getVocId())
        );

        if (existing != null) {
            return; // 已存在则不重复添加
        }

        // 创建新的收藏记录
        UserFavoriteDO newFavorite = new UserFavoriteDO();
        newFavorite.setUserId(userId);
        newFavorite.setVocId(Long.valueOf(userFavoriteCommand.getVocId()));
        newFavorite.setVocContent(userFavoriteCommand.getVocContent());

        // 检查是否已选择复习
        UserVocRevDO reviewRecord = userVocRevMapper.selectOne(
                new LambdaQueryWrapper<UserVocRevDO>()
                        .eq(UserVocRevDO::getUserId, userId)
                        .eq(UserVocRevDO::getVocId, userFavoriteCommand.getVocId())
        );
        newFavorite.setSelected(reviewRecord != null ? 1 : 0);

        userFavoriteMapper.insert(newFavorite);
    }

    /**
     * 取消收藏单词
     *
     * @param ids
     * @param userId
     */
    @Override
    public void cancelFavorite(List<Long> ids, Long userId) {

        if (ids == null || ids.isEmpty()) {
            return;
        }

        userFavoriteMapper.delete(
                new LambdaQueryWrapper<UserFavoriteDO>()
                        .eq(UserFavoriteDO::getUserId, userId)
                        .in(UserFavoriteDO::getVocId, ids)
        );
    }

    /**
     * 获取用户收藏单词列表
     *
     * @param pageRequest
     * @param userId
     * @return
     */
    @Override
    public PageDTO<UserFavoriteDTO> getUserFavoriteList(PageRequest pageRequest, Long userId) {
        // 1. 分页查询收藏记录
        Page<UserFavoriteDO> page = new Page<>(pageRequest.getPageNum(), pageRequest.getCount());

        IPage<UserFavoriteDO> favoritePage = userFavoriteMapper.selectPage(page,
                new LambdaQueryWrapper<UserFavoriteDO>()
                        .eq(UserFavoriteDO::getUserId, userId)
        );

        if (favoritePage.getRecords().isEmpty()) {
            return new PageDTO<>(Collections.emptyList(), 0L);
        }

        // 2. 获取所有单词ID
        List<Long> vocIds = favoritePage.getRecords().stream()
                .map(UserFavoriteDO::getVocId)
                .collect(Collectors.toList());

        // 3. 批量查询单词释义
        Map<Long, List<VocMeaningDO>> meaningsMap = vocMeaningMapper.selectList(
                new LambdaQueryWrapper<VocMeaningDO>()
                        .in(VocMeaningDO::getVocId, vocIds)
        ).stream().collect(Collectors.groupingBy(VocMeaningDO::getVocId));

        // 4. 批量查询复习状态
        Set<Long> reviewedVocIds = userVocRevMapper.selectList(
                new LambdaQueryWrapper<UserVocRevDO>()
                        .eq(UserVocRevDO::getUserId, userId)
                        .in(UserVocRevDO::getVocId, vocIds)
        ).stream().map(UserVocRevDO::getVocId).collect(Collectors.toSet());

        // 5. 组装DTO
        List<UserFavoriteDTO> dtos = favoritePage.getRecords().stream()
                .map(favorite -> {
                    UserFavoriteDTO dto = new UserFavoriteDTO();
                    dto.setVocId(String.valueOf(favorite.getVocId()));
                    dto.setVocContent(favorite.getVocContent());
                    dto.setSelected(reviewedVocIds.contains(favorite.getVocId()) ? 1 : 0);

                    // 转换释义
                    List<VocMeaningDO> meanings = meaningsMap.getOrDefault(favorite.getVocId(), Collections.emptyList());
                    List<DisplayVocInterpretationDTO> interpretationDTOs = meanings.stream()
                            .map(meaning -> {
                                DisplayVocInterpretationDTO interpretation = new DisplayVocInterpretationDTO();
                                interpretation.setType(meaning.getType());
                                interpretation.setContent(meaning.getInterContent());
                                return interpretation;
                            })
                            .collect(Collectors.toList());
                    dto.setInterpretations(interpretationDTOs);

                    return dto;
                })
                .collect(Collectors.toList());

        return new PageDTO<>(dtos, favoritePage.getTotal());
    }

    /**
     * 添加用户自建例句
     *
     * @param command
     * @param userId
     */
    @Override
    public void addUserVocSentence(UserVocExampleSentenceCommand command, Long userId) {
        command.setUserId(userId.toString());
        userVocExampleSentenceMapper.insert(userPrivilegeConverter.userVocExampleSentenceCommand2DO(command));
    }

    /**
     * 获取用户自建例句
     *
     * @param pageRequest
     * @param userId
     * @return
     */
    @Override
    public PageDTO<DisplayUserVocSentenceDTO> getUserVocSentence(PageRequest pageRequest, Long userId) {
        // 创建查询条件，只查询当前用户的例句
        QueryWrapper<UserVocExampleSentenceDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);

        if (pageRequest.getPageNum() == null) {
            // 不分页查询
            List<UserVocExampleSentenceDO> userSentenceDOs = userVocExampleSentenceMapper.selectList(queryWrapper);

            // 转换为 UserVocSentenceDTO
            List<UserVocSentenceDTO> sentenceDTOs = userPrivilegeConverter.userVocSentenceDOs2DTOs(userSentenceDOs);

            // 转换为 DisplayUserVocSentenceDTO
            List<DisplayUserVocSentenceDTO> displayDTOs = userPrivilegeConverter.userVocSentenceDTOs2DisplayDTOs(sentenceDTOs);

            // 创建分页结果
            return userPrivilegeConverter.displayUserVocSentenceDTOList2PageDTO(displayDTOs, (long) userSentenceDOs.size());
        } else {
            // 分页查询
            Page<UserVocExampleSentenceDO> page = new Page<>(pageRequest.getPageNum(), pageRequest.getCount());
            Page<UserVocExampleSentenceDO> resultPage = userVocExampleSentenceMapper.selectPage(page, queryWrapper);

            // 转换为 UserVocSentenceDTO
            List<UserVocSentenceDTO> sentenceDTOs = userPrivilegeConverter.userVocSentenceDOs2DTOs(resultPage.getRecords());

            // 转换为 DisplayUserVocSentenceDTO
            List<DisplayUserVocSentenceDTO> displayDTOs = userPrivilegeConverter.userVocSentenceDTOs2DisplayDTOs(sentenceDTOs);

            // 创建分页结果
            return userPrivilegeConverter.displayUserVocSentenceDTOList2PageDTO(displayDTOs, resultPage.getTotal());
        }
    }

    /**
     * 更新用户自建例句
     *
     * @param command
     * @param userId
     */
    @Override
    public void updateUserVocSentence(UserVocExampleSentenceCommand command, Long userId) {
        command.setUserId(userId.toString());
        userVocExampleSentenceMapper.updateById(userPrivilegeConverter.userVocExampleSentenceCommand2DO(command));
    }

    @Override
    public void deleteUserVocSentence(Long id) {

    }

    /**
     * 标识不想背
     *
     * @param vocId
     * @param userId
     */
    @Override
    public void notRemember(Long vocId, Long userId) {

        // 1. 检查是否已存在记录
        UserNotRememberDO existingRecord = userNotRememberMapper.selectOne(
                new LambdaQueryWrapper<UserNotRememberDO>()
                        .eq(UserNotRememberDO::getUserId, userId)
                        .eq(UserNotRememberDO::getVocId, vocId)
        );

        if (existingRecord == null) {
            // 2. 添加到user_not_remember表
            UserNotRememberDO newRecord = new UserNotRememberDO();
            newRecord.setUserId(userId);
            newRecord.setVocId(vocId);
            userNotRememberMapper.insert(newRecord);
        }

        // 3. 检查并删除user_voc_rev表中的记录
        UserVocRevDO vocRevRecord = userVocRevMapper.selectOne(
                new LambdaQueryWrapper<UserVocRevDO>()
                        .eq(UserVocRevDO::getUserId, userId)
                        .eq(UserVocRevDO::getVocId, vocId)
        );

        if (vocRevRecord != null) {
            userVocRevMapper.delete(
                    new LambdaQueryWrapper<UserVocRevDO>()
                            .eq(UserVocRevDO::getUserId, userId)
                            .eq(UserVocRevDO::getVocId, vocId)
            );
        }
    }

    /**
     * 取消标识不想背
     *
     * @param vocId
     * @param userId
     */
    @Override
    public void cancelNotRemember(Long vocId, Long userId) {

        // 直接从user_not_remember表中删除记录
        userNotRememberMapper.delete(
                new LambdaQueryWrapper<UserNotRememberDO>()
                        .eq(UserNotRememberDO::getUserId, userId)
                        .eq(UserNotRememberDO::getVocId, vocId)
        );
    }

    @Override
    public List<UserReviewFillWordDTO> getUserReviewFillWordTopics(List<Long> vocIds) {
        return null;
    }

    @Override
    public List<UserReviewSingleChoiceDTO> getVocSingleChoiceTopic(List<Long> vocIds) {
        return null;
    }

    /**
     * 获取AI阅读模式以及选项
     *
     * @return
     */
    @Override
    public List<UserVocAISituationDTO> getAIReviewReadOptions() {
        // 1. 查询主表数据
        QueryWrapper<UserVocAISituationDO> situationQuery = new QueryWrapper<>();
        situationQuery.orderByAsc("id");
        List<UserVocAISituationDO> situations = userVocAISituationMapper.selectList(situationQuery);

        if (CollectionUtils.isEmpty(situations)) {
            return Collections.emptyList();
        }

        // 2. 获取主表ID集合（保持Long类型用于查询）
        List<Long> situationIds = situations.stream()
                .map(UserVocAISituationDO::getId)
                .collect(Collectors.toList());

        // 3. 查询子表数据
        QueryWrapper<UserVocAISituationOptionDO> optionQuery = new QueryWrapper<>();
        optionQuery.in("situation_id", situationIds);
        List<UserVocAISituationOptionDO> options = userVocAISituationOptionMapper.selectList(optionQuery);

        // 4. 转换主表数据为DTO（提前转换以便后续使用）
        List<UserVocAISituationDTO> dtos = userPrivilegeConverter.userVocAISituationDOs2DTOs(situations);

        // 5. 构建DTO ID -> 子表数据的映射（注意保持类型一致）
        Map<String, List<UserVocAISituationOptionDO>> optionsMap = options.stream()
                .collect(Collectors.groupingBy(
                        opt -> opt.getSituationId().toString() // 确保key类型与DTO ID类型匹配
                ));

        // 6. 设置子项
        dtos.forEach(dto -> {
            List<UserVocAISituationOptionDO> subOptions =
                    optionsMap.getOrDefault(dto.getId(), Collections.emptyList());
            dto.setOptions(userPrivilegeConverter.userVocAISituationOptionDOs2DTOs(subOptions));
        });

        return dtos;
    }

    /**
     * 获取用户剩余免费AI阅读次数
     *
     * @param userId
     * @return
     */
    @Override
    public Integer getUserVocAIReadRemainFreeCount(Long userId) {
        QueryWrapper<UserPrivilegeUseStatisticsDO> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        UserPrivilegeUseStatisticsDO statistics = userPrivilegeHistoryMapper.selectOne(wrapper);
        if (statistics == null) {
            UserPrivilegeUseStatisticsDO statistic = new UserPrivilegeUseStatisticsDO();
            statistic.setUserId(userId);      // 设置userId
            statistic.setUseCount(0);       // 设置默认值0

            // 如果需要立即保存到数据库
            userPrivilegeHistoryMapper.insert(statistic);
            return (10-statistic.getUseCount());
        } else if (statistics.getUseCount() >= 10) {
            return 0;

        }
        return (10-statistics.getUseCount());
    }

    /**
     * 获取AI阅读内容
     *
     * @param command
     * @param userId
     * @return
     */
    @Override
    public List<AIReviewReadDTO> getAIReviewReadContent(AIReviewReadCommand command, Long userId) {
        // 1. 参数校验
        validateCommand(command);

        // 2. 检查使用限制
        checkUsageLimit(userId);
        List<AIReviewReadDTO> content = aiReadGenerator.generateReadContent(command);
        afterSuccess(userId);
        return content;
    }

    private void afterSuccess(Long userId) {
        // 1. 更新使用统计
        updateUsageStatistics(userId);

        // 2. 扣减单词上限并记录日志（仅在超过免费次数时）
        UserPrivilegeUseStatisticsDO currentStats = userPrivilegeHistoryMapper.selectOne(
                new LambdaQueryWrapper<UserPrivilegeUseStatisticsDO>()
                        .eq(UserPrivilegeUseStatisticsDO::getUserId, userId)
                        .eq(UserPrivilegeUseStatisticsDO::getPrivilegeCode, "review:ai:read"));

        if (currentStats.getUseCount() > 10) {
            // 扣减单词上限
            int updated = userVocBoundStatisticsMapper.deductAvailable(userId, 10);
            if (updated == 0) {
                throw new BusinessException(ResultCodeEnum.USER_VOC_BOUND_NOT_ENOUGH);
            }

            // 记录单词上限变化日志
            createBoundLog(userId);
        }
    }

    private void updateUsageStatistics(Long userId) {
        int updated = userPrivilegeHistoryMapper.incrementUseCount(
                userId, "review:ai:read", 1);

        if (updated == 0) {
            UserPrivilegeUseStatisticsDO statistics = new UserPrivilegeUseStatisticsDO();
            statistics.setUserId(userId);
            statistics.setPrivilegeCode("review:ai:read");
            statistics.setUseCount(1);
            userPrivilegeHistoryMapper.insert(statistics);
        }
    }

    private void createBoundLog(Long userId) {
        UserVocBoundLogDO log = UserVocBoundLogDO.builder()
                .userId(userId)
                .type(CommonConstant.USER_VOC_BOUND_CHANGE_TYPE_EXCHANGE)
                .logDate(LocalDate.now())
                .count(-10) // 扣减10个
                .description(CommonConstant.USER_VOC_BOUND_DESCRIPTION_AI_READ)
                .build();

        userVocBoundLogMapper.insert(log);
    }

    private void checkUsageLimit(Long userId) {
        // 查询使用统计
        UserPrivilegeUseStatisticsDO statistics = userPrivilegeHistoryMapper.selectOne(
                new LambdaQueryWrapper<UserPrivilegeUseStatisticsDO>()
                        .eq(UserPrivilegeUseStatisticsDO::getUserId, userId)
                        .eq(UserPrivilegeUseStatisticsDO::getPrivilegeCode, "review:ai:read"));

        // 如果已使用10次或更多，检查单词上限
        if (statistics != null && statistics.getUseCount() >= 10) {
            UserVocBoundStatisticsDO bound = userVocBoundStatisticsMapper.selectOne(
                    new LambdaQueryWrapper<UserVocBoundStatisticsDO>()
                            .eq(UserVocBoundStatisticsDO::getUserId, userId));

            if (bound == null || bound.getAvailable() < 10) {
                throw new BusinessException(ResultCodeEnum.USER_VOC_BOUND_NOT_ENOUGH);
            }
        }
    }

    private void validateCommand(AIReviewReadCommand command) {
        if (command == null || CollectionUtils.isEmpty(command.getVocList())) {
            throw new IllegalArgumentException("请求参数不合法");
        }
    }

}
